using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Game;
using NetProtocol.POD;

namespace IQIGame.Onigao.GamePlay
{
    public class BattleRenderContrller : TController
    {
        public BattleData data;

        private BattleRenderSceneController _mRenderSceneCtrl;
        private BattleRenderQueueController _mQueueCtrl;
        private BattleOrderContrller _mOrderCtrl;
        private BattleRenderTurnController _mTurnCtrl;
        private BattleRenderCloseUpController _mCloseUpCtrl;
        private BattleRenderCollisionController _mCollisionCtrl;
        private BattleTouchController _mTouchController;
        private BattleRenderHideController _mHideCtrl;

        public BattleRenderSceneController sceneCtrl => this._mRenderSceneCtrl;
        public BattleRenderQueueController queueCtrl => this._mQueueCtrl;
        public BattleOrderContrller orderCtrl => this._mOrderCtrl;
        public BattleRenderTurnController turnCtrl => this._mTurnCtrl;
        public BattleRenderCloseUpController closeUpCtrl => _mCloseUpCtrl;
        public BattleRenderCollisionController collisionCtrl => _mCollisionCtrl;
        public BattleTouchController touchCtrl => _mTouchController;
        public BattleRenderHideController hideCtrl => this._mHideCtrl;

        // private Battle
        public async UniTask Initialize(BattleEnterPOD result)
        {
            this._mRenderSceneCtrl = new BattleRenderSceneController();
            this.AddSubController(this._mRenderSceneCtrl);
            this._mQueueCtrl = new BattleRenderQueueController();
            this.AddSubController(this._mQueueCtrl);
            this._mOrderCtrl = new BattleOrderContrller();
            this.AddSubController(this._mOrderCtrl);
            this._mTurnCtrl = new BattleRenderTurnController();
            this.AddSubController(this._mTurnCtrl);
            this._mCloseUpCtrl = new BattleRenderCloseUpController();
            this.AddSubController(this._mCloseUpCtrl);
            this._mCollisionCtrl = new BattleRenderCollisionController();
            this.AddSubController(this._mCollisionCtrl);
            this._mTouchController = new BattleTouchController();
            this.AddSubController(this._mTouchController);
            this._mHideCtrl = new BattleRenderHideController();
            this.AddSubController(this._mHideCtrl);

            this.data = new BattleData();
            this.data.Initialize(result);

            var rSceneConfig = TableCenter.battleScene.Get(result.battleScene);
            await this.sceneCtrl.Initialize(this, rSceneConfig);
            await this.queueCtrl.Initialize(this);
            await this.orderCtrl.Initialize(this);
            await this.turnCtrl.Initialize(this);
            await this.closeUpCtrl.Initialize(this);
            await this.touchCtrl.Initialize(this);

            // 激活对象池
            ManagerCenter.Entity.EnableGroup((int)EntityPoolGroupType.BattleUnit);
            ManagerCenter.Entity.EnableGroup((int)EntityPoolGroupType.BattleSceneEntity);

            var rAllUnits = this.data.units;
            for (int i = 0; i < rAllUnits.Count; i++)
            {
                await rAllUnits[i].InitializeView();
                rAllUnits[i].GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent).Enable();
            }
            
            // Preload
            await this.Preload();
        }

        public async UniTask Restart(BattleEnterPOD result)
        {
            // 移除所有单位
            var rAllUnits = this.data.units;
            for (int i = 0; i < rAllUnits.Count; i++)
            {
                rAllUnits[i].Dispose();
            }
            // UI要重新启动
            this.orderCtrl.Dispose();
            
            this.data.Initialize(result);
            
            var rSceneConfig = TableCenter.battleScene.Get(result.battleScene);
            await this.sceneCtrl.Restart(rSceneConfig);
            this.queueCtrl.Clear();
            await this.orderCtrl.Initialize(this);
            
            rAllUnits = this.data.units;
            for (int i = 0; i < rAllUnits.Count; i++)
            {
                await rAllUnits[i].InitializeView();
                rAllUnits[i].GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent).Enable();
            }
        }

        protected override void OnUpdate(float deltaTime)
        {
            base.OnUpdate(deltaTime);
            var nLen = this.data.units.Count;
            for (int i = 0; i < nLen; i++)
            {
                var nIndex = nLen - i - 1;
                this.data.units[nIndex].OnUpdate(deltaTime);
            }
        }

        public async UniTask OnNextWave(BattleTeamViewPOD rBattleTeam)
        {
            this.data.RemoveMonsterTeam(rBattleTeam);
            this.data.SetTeam(rBattleTeam);

            if (this.data.teams.TryGetValue(BattleConst.TeamBlueIndex, out var rTeamData))
            {
                for (int i = 0; i < rTeamData.units.Count; i++)
                {
                    var rUnit = rTeamData.units[i];
                    await rUnit.InitializeView();
                    rUnit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent).Enable();
                }
            }
        }

        protected override void OnDispose()
        {
            // 关闭对象池
            ManagerCenter.Entity.DisableGroup((int)EntityPoolGroupType.BattleUnit);
            ManagerCenter.Entity.DisableGroup((int)EntityPoolGroupType.BattleSceneEntity);
        }
        
        private UniTask Preload()
        {
            var rList = new List<UniTask>();
            for (int i = 0; i < this.data.units.Count; i++)
            {
                var rEffects = EffectReuseGlobal.GetEffects(this.data.units[i].roleName);
                if (rEffects != null)
                {
                    for (int j = 0; j < rEffects.Count; j++)
                    {
                        var rEffectName = rEffects[j];
                        rList.Add(this.PreloadEffect(this.data.units[i],rEffectName));
                    }
                }
            }
            return UniTask.WhenAll(rList);
        }
        
        private async UniTask PreloadEffect(UnitView unit, string effectName)
        {
            var rEffectComp = unit.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
            if (rEffectComp != null)
            {
                var rEffectPath = rEffectComp.GetRoleEffectPath(effectName);
                var rEntity = ManagerCenter.Entity.Get(rEffectPath, (int)EntityPoolGroupType.BattleSceneEntity) as BattleSceneEntityView;
                await rEntity.Load();
                rEntity.Put();
            }
        }
    }
}